package com.token.sysflow.hander;

import com.alibaba.fastjson.JSONObject;
import com.token.sql.IntegrateSql;
import com.token.sql.PrepareSql;
import com.token.sysflow.bean.*;
import com.token.sysflow.enumerate.StepTypeEnum;
import com.token.sysflow.exception.ErrorCodeEnum;
import com.token.sysflow.exception.FlowException;
import com.token.sysflow.service.JavaScriptUtil;
import lombok.Getter;
import lombok.Setter;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 * 环节
 * @author chenjianxiong
 */
public class Step extends FlowStepBasic {

    private FlowStepApprover approver;
    private FlowStepControl control;
    private FlowStepNotifySub notifySub;
    private FlowStepSwitchFunc stepSwitchFunc;

    @Getter
    @Setter
    private String pathId = null;

    @Getter
    private final boolean isHas;

    /**
     *
     * @param iSql
     * @param stepId
     * @throws Exception
     */
    public Step(IntegrateSql iSql, String stepId) throws Exception {
        super(iSql,stepId);
        isHas = this.isInitRs();
    }

    /**
     *
     * @param iSql
     * @param rs
     * @throws Exception
     */
    public Step(IntegrateSql iSql, ResultSet rs) throws Exception {
        super(iSql,rs);
        isHas = true;
    }


    /**
     * 获取环节控制
     * @return FlowStepControl
     * @throws Exception 抛出错误
     */
    public FlowStepControl getStepControl() throws Exception {
        if (control == null) {
            control = new FlowStepControl(this.getIntegrateSql(), this.getStepId());
        }
        return control;
    }


    /**
     * 获取默认办理意见
     * @return String
     * @throws Exception  抛出错误
     */
    public String getDefaultOpinion() throws Exception {
        if (control == null) {
            control = new FlowStepControl(this.getIntegrateSql(), this.getStepId());
        }
        return control.getDefaultOpinion();
    }

    /**
     * 功能开关
     * @return FlowStepSwitchFunc
     * @throws Exception 抛出错误
     */
    public FlowStepSwitchFunc getStepSwitchFunc() throws Exception {
        if (stepSwitchFunc == null) {
            stepSwitchFunc = new FlowStepSwitchFunc(this.getIntegrateSql(), this.getStepId());
        }
        return stepSwitchFunc;
    }

    public boolean isCanSubmitRePerson() throws Exception {
        if (stepSwitchFunc == null) {
            stepSwitchFunc = new FlowStepSwitchFunc(this.getIntegrateSql(), this.getStepId());
        }
        return stepSwitchFunc.getCanSubmitRePerson().equals("1");
    }


    /**
     * 取回开关是否开启
     * @return boolean
     * @throws Exception
     */
    public boolean isCanBack() throws Exception{
        return getStepSwitchFunc().getCanBack().equals("1");
    }

    /**
     * 组织会签开关是否开启
     * @return
     * @throws Exception
     */
    public boolean isCanOrgSign() throws Exception{
        return getStepSwitchFunc().getCanOrgSign().equals("1");
    }

    /**
     * 组织会审开关是否开启
     * @return
     * @throws Exception
     */
    public boolean isCanCame() throws Exception{
        return getStepSwitchFunc().getCanCame().equals("1");
    }
    /**
     * 退回开关是否开启
     * @return
     * @throws Exception
     */
    public boolean isCanReturn() throws Exception{
        return getStepSwitchFunc().getCanReturn().equals("1");
    }
    /**
     * 作废开关是否开启
     * @return
     * @throws Exception
     */
    public boolean isCanOver() throws Exception{
        return getStepSwitchFunc().getCanOver().equals("1");
    }

    /**
     * 选择方式
     * @return true 可修改  false 不可修改
     * @throws Exception
     */
    public boolean isSelectWayCheck() throws Exception{
        return getStepSwitchFunc().getSelectWayCheck().equals("1");
    }

    /**
     * 环节选择方式
     * @return String
     */
    public String getSelectWay() throws Exception{
        return getStepSwitchFunc().getSelectWay();
    }

    /**
     * 环节选择方式
     * @return String
     */
    public boolean isNoChecked() throws Exception{
        return getStepSwitchFunc().getNoChecked().equals("1");

    }
    /**
     * 转审开关是否开启
     * @return
     * @throws Exception
     */
    public boolean isCanOther() throws Exception{
        return getStepSwitchFunc().getCanOther().equals("1");
    }

    /**
     * 会审策略
     * @return 会审策略;通过数量;关键办理人
     * @throws Exception
     */
    public String getStepHSAllWay() throws Exception {
        if (approver == null) {
            approver = new FlowStepApprover(this.getIntegrateSql(), this.getStepId());
        }
        return approver.getHSway() + ";" + approver.getHSnum() + ";" + approver.getKeyUser();
    }

    /**
     * 获取默认的下一环节
     * @return Step
     */
    public Step getDefaultNextStep(JSONObject json) throws Exception{
        List<Step> arrayList = getAllNextStep(json);
        if(arrayList.size() == 0){
            throw new FlowException(ErrorCodeEnum.PATHSTEP_NOFIND);
        }
        return arrayList.get(0);
    }

    /**
     * 获取指定流向
     * @param pathNo 流向编号
     * @return
     * @throws Exception
     */
    public List<Step> getThePathNextStep(Object pathNo) throws Exception {
        PrepareSql tSql = new PrepareSql(this.getIntegrateSql());
        StringBuffer sql = new StringBuffer(50);
        sql.append("select s.*,p.PathId from ")
                .append(this.getTableName()).append(" s inner join ").append(FlowPathInfo.TABLE_NAME)
                .append(" p on s.").append(this.getKeyName()).append("=p.ToStepId")
                .append(" where p.FromStepId=? and p.SerialNumber=?");
        tSql.setPrepare(sql);
        tSql.setPstValue(1,this.getStepId());
        tSql.setPstValue(2,pathNo);
        return getStep(tSql.executeQuery(),null);
    }

    /**
     * 获取环节
     * @param rs 结果集
     * @return LIST
     * @throws Exception
     */
    private List<Step> getStep(ResultSet rs,JSONObject json) throws Exception{
        List<Step> arrayList = new ArrayList<>();
        if(rs.next()){
            Step basic;
            do {
                basic = new Step(this.getIntegrateSql(),rs);
                if(basic.getStepType().equals(StepTypeEnum.STEPTYPE_FORK.getTypeKey())){ //决策
                    if(basic.getForkCondition().equals("")){
                        throw new FlowException(ErrorCodeEnum.FORKCONDITION_NOFIND);
                    }else{
                        arrayList.addAll(basic.getThePathNextStep(JavaScriptUtil.execute(JavaScriptUtil.replaceStr(basic.getForkCondition(),json))));
                    }
                }else{
                    arrayList.add(basic);
                }
            }while (rs.next());
        }
        rs.close();
        return arrayList;
    }
    /**
     * 获取下一环节的所有流向环节
     * @return List
     */
    public List<Step> getAllNextStep(JSONObject json) throws Exception {
        PrepareSql tSql = new PrepareSql(this.getIntegrateSql());
        StringBuffer sql = new StringBuffer(50);
        sql.append("select s.*,p.PathId ")
                .append("from ")
                .append(this.getTableName()).append(" s inner join ").append(FlowPathInfo.TABLE_NAME)
                .append(" p on s.").append(this.getKeyName()).append("=p.ToStepId")
                .append(" where p.FromStepId=? order by p.SerialNumber");
        tSql.setPrepare(sql);
        tSql.setPstValue(1,this.getStepId());
        return getStep(tSql.executeQuery(),json);
    }

    /**
     * 关闭
     */
    public void close(){
        try {
            super.close();
            if (approver != null) approver.close();
        } catch (SQLException throwables) {
            throwables.printStackTrace();
        }
    }
}